﻿using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using NthDownload.Contracts;
using NthDownload.Contracts.Plugins.Downloads;
using NthDownload.Common.Utils;
using NthDownload.Composition;
using System.ComponentModel.Composition;

namespace NthDownload.DownloadPlugins.Http
{
    public class HttpDownloadFactory : IDownloadFactory
    {
        #region Class Members

        private readonly string _pluginGUID;

        #endregion Class Members

        #region Constructors

        public HttpDownloadFactory(string pluginGUID)
        {
            _pluginGUID = pluginGUID;
            SatisfyImports();
        }

        #endregion Constructors

        #region Properties

        /// <summary>
        /// Current Settings
        /// </summary>
        [Import(AllowRecomposition = true)]
        public HttpSettings Settings { get; set; }

        #endregion Properties

        #region Methods

        public IDownload CreateDownload(string path, string destinationPath)
        {
            HttpDownload download = new HttpDownload(path);
            Uri uri = new Uri(path);
            string lastSegment = uri.Segments.LastOrDefault();

            download.GUID = Guid.NewGuid().ToString();
            download.ParentGUID = _pluginGUID;
            download.FileName = (lastSegment == "/" || lastSegment == "") ? path.Remove(Path.GetInvalidFileNameChars().Concat(new char[] {'.'}).ToArray()) : lastSegment.Remove(Path.GetInvalidFileNameChars());//Path.GetFileName(sourcePath);
            download.Description = (lastSegment == "/" || lastSegment == "") ? path : lastSegment; //Path.GetFileName(sourcePath);
            download.DestinationFolder = destinationPath;
            download.DateCreated = DateTime.Now;
            download.Status = DownloadStatuses.Ready;

            return download;
        }

        public Task InitializeDownload(IDownload download)
        {
            Task task = new Task(() =>
            {
                HttpDownload localDownload = download as HttpDownload;

                //TODO Tidy how the credentials are generated
                CredentialCache myCache = new CredentialCache();
                foreach (var credentials in Settings.Credentials)
                {
                    myCache.Add(new Uri(credentials.Domain), "Basic", new NetworkCredential(credentials.Username, credentials.Password));
                    myCache.Add(new Uri(credentials.Domain), "Digest", new NetworkCredential(credentials.Username, credentials.Password));
                }

                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(localDownload.Path);
                //TODO Add setting for time out
                //request.Timeout = 1000;
                request.AddRange(0);
                request.Credentials = myCache;
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                //TODO Add setting for chunk size
                localDownload.ChunkSize = 1024 * 32;
                localDownload.CanQueue = true;
                localDownload.CanResume = (response.ContentLength > 0) && (response.StatusCode == HttpStatusCode.PartialContent);
                localDownload.HasSize = response.ContentLength > 0;
                localDownload.IsInitialized = true;
                localDownload.Size = response.ContentLength;

                response.Close();
            });

            task.Start();

            return task;
        }

        #endregion Methods

        #region Protected Methods

        /// <summary>
        /// Satisfies imports for the current view model
        /// </summary>
        protected void SatisfyImports()
        {
            ImportService.TrySatisfyImports(this);
        }

        #endregion Protected Methods
    }
}
